/*
 * Copyright (c) 2008 Kevin Wetzels
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package be.roam.jindy.string;

/**
 * Utility methods for dealing with paths (mostly URL).
 * 
 * @author Kevin Wetzels
 * 
 */
public class PathUtils {

	/**
	 * Builds a path from the given strings in unix style.
	 * 
	 * @param elements
	 *            path elements
	 * @return the path
	 * 
	 * @see #build(boolean, String...)
	 */
	public static String build(String... elements) {
		return build(true, elements);
	}

	/**
	 * Builds a path from the given strings, removing slashes/backslashes at the
	 * start or the end of the strings.
	 * <p>
	 * What this means is that passing <code>http://localhost:8080/</code> and
	 * <code>/webapp/</code> will result in
	 * <code>http://localhost:8080/webapp/</code> instead of
	 * <code>http://localhost:8080/<b>/</b>webapp</code>.
	 * </p>
	 * 
	 * @param unixStyle
	 *            <code>true</code> means use slashes, <code>false</code> means
	 *            you prefer backslashes
	 * @param elements
	 *            the parts to tie together
	 * @return the concatenated path
	 */
	public static String build(boolean unixStyle, String... elements) {
		int length = elements.length;
		StringBuilder builder = new StringBuilder(length * 10);
		for (int index = 0; index < length; ++index) {
			String element = elements[index];
			element = element.replace('\\', '/');
			while (element.length() > 0 && element.startsWith("/")) {
				element = element.substring(1);
			}
			builder.append(element);
			if (!element.endsWith("/") && element.length() > 0 && index < length - 1) {
				builder.append("/");
			}
		}
		return builder.toString();
	}

	/**
	 * Checks if the path ends with the part.
	 * <p>
	 * These will return true:
	 * </p>
	 * <ul>
	 * <li><code>/aaa/bbb/ccc</code> and <code>ccc</code></li>
	 * <li><code>/aaa/bbb/ccc/</code> and <code>ccc</code></li>
	 * <li><code>/aaa/bbb/ccc?keywords=search</code> and <code>ccc</code></li>
	 * <li><code>/aaa/bbb/ccc/?keywords=search</code> and <code>ccc</code></li>
	 * </ul>
	 * <p>
	 * These will <strong>not</strong>:
	 * </p>
	 * <ul>
	 * <li><code>/aaa/bbb/ccc</code> and <code>cc</code></li>
	 * <li><code>/aaa/bbb/ccc//</code> and <code>ccc</code></li>
	 * </ul>
	 * 
	 * @param path
	 *            the path (Windows path separators are replaced with Unix path
	 *            separators)
	 * @param part
	 *            the part that should match the last part of the path
	 * @return <code>true</code> when the part matches the last part of the path
	 */
	public static boolean endsWith(String path, String part) {
		if (path == null || part == null) {
			return false;
		}
		// Replace Windows path separators with Unix separators and strip an
		// optional query string from the path
		path = stripQueryString(path.replace('\\', '/'));
		if (path.endsWith("/")) {
			int pathLength = path.length();
			if (pathLength > 1) {
				path = path.substring(0, path.length() - 1);
			} else {
				path = "";
			}
		}
		// Remove the path separators from the part
		part = part.replace("\\", "").replace("/", "");

		int indexOfLastPath = path.lastIndexOf('/');
		if (indexOfLastPath < 0) {
			// The path does not contain a slash (and the part no longer does)
			// which means it simply should be equal to the path or not
			return part.equals(path);
		}
		if (indexOfLastPath + 1 == path.length()) {
			// The path simply is a slash, which means the part will match if
			// it's an empty string
			return "".equals(part);
		}
		String lastPartOfPath = path.substring(indexOfLastPath + 1);
		return lastPartOfPath.equals(part);
	}

	/**
	 * Strips the query string from a URL.
	 * <p>
	 * <code>stripQueryString("/url/sub/index.php?key=abc&123=654")</code> will
	 * return <code>"/url/sub/index.php"</code>.
	 * </p>
	 * 
	 * @param url
	 *            url to strip the query string from
	 * @return the url without a query string
	 */
	public static String stripQueryString(String url) {
		if (url == null) {
			return url;
		}
		int index = url.indexOf('?');
		if (index >= 0) {
			return url.substring(0, index);

		}
		return url;
	}

}
